package cool.taomu.toolkit.asm

import java.lang.reflect.Method
import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.ClassWriter
import org.objectweb.asm.Opcodes
import org.objectweb.asm.Type
import java.lang.annotation.Annotation

/**
 * 使用 ASM 动态生成接口的默认实现类，并加载到 JVM 中
 */
class AsmClassLoader extends ClassLoader {

    // static final String OBJECT_DESCRIPTOR = Type.getDescriptor(Object)
    val String CLASS_SUFFIX = "_ASM_Impl"

    /**
     * 为指定接口生成一个空实现类
     */
    def Class<?> defineClassForInterface(Class<?> intf) {
        val className = intf.getName().replace('.', '/') + CLASS_SUFFIX
        val classBytes = generateImplClass(intf, className)
        return defineClass(className.replace('/', '.'), classBytes, 0, classBytes.length)
    }

    /**
     * 使用 ASM 动态生成类字节码
     */
    def private byte[] generateImplClass(Class<?> intf, String className) {
        val cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES + ClassWriter.COMPUTE_MAXS)

        val visitor = cw
        // 构造类头
        visitor.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, className, null, "java/lang/Object",
            #[intf.name.replace('.', '/')])

        // 添加：复制接口上的所有注解到类上
        for (Annotation ann : intf.getAnnotations()) {
            val visitor2 = cw.visitAnnotation(Type.getDescriptor(ann.annotationType()), true)
            writeAnnotation(visitor2, ann)
            visitor?.visitEnd()
        }
        // 默认构造函数
        generateDefaultConstructor(visitor)

        // 生成接口中所有方法的空实现
        for (Method method : intf.getDeclaredMethods()) {
            generateEmptyMethodImpl(visitor, method, intf)
        }

        visitor.visitEnd()
        return cw.toByteArray()
    }

    /**
     * 写入单个注解到类/方法上
     */
    def private void writeAnnotation(org.objectweb.asm.AnnotationVisitor visitor, Annotation ann) {
        for (Method m : ann.annotationType().getDeclaredMethods()) {
            val name = m.getName()
            val value = m.invoke(ann)
            writeAnnotationValue(visitor, name, value)
        }
    }

    /**
     * 写入注解的字段值（支持数组、嵌套注解等）
     */
    def private void writeAnnotationValue(org.objectweb.asm.AnnotationVisitor visitor, String name, Object value) {
        if (value instanceof Annotation) {
            val subVisitor = visitor.visitAnnotation(name, Type.getDescriptor(value.annotationType()))
            writeAnnotation(subVisitor, value as Annotation)
            subVisitor?.visitEnd()
        } else if (value instanceof Object[]) {
            val arrayVisitor = visitor.visitArray(name)
            for (Object element : value as Object[]) {
                writeAnnotationValue(arrayVisitor, null, element)
            }
            arrayVisitor?.visitEnd()
        } else {
            visitor.visit(name, value)
        }
    }

    /**
     * 生成默认构造函数
     */
    def generateDefaultConstructor(ClassVisitor visitor) {
        val mv = visitor.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null)
        mv.visitVarInsn(Opcodes.ALOAD, 0)
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false)
        mv.visitInsn(Opcodes.RETURN)
        mv.visitMaxs(1, 1)
        mv.visitEnd()
    }

    /**
     * 生成空方法体
     */
    def generateEmptyMethodImpl(ClassVisitor visitor, Method method, Class<?> intf) {
        val desc = Type.getMethodDescriptor(method)
        val exceptions = method.exceptionTypes.map[Type.getInternalName(it)].toList
        val mv = visitor.visitMethod(Opcodes.ACC_PUBLIC, method.getName(), desc, null, exceptions)
// ========== 新增：复制接口方法上的注解 ==========
        for (Annotation ann : method.getDeclaredAnnotations()) {
            val av = mv.visitAnnotation(Type.getDescriptor(ann.annotationType()), true)
            writeAnnotation(av, ann)
            av?.visitEnd()
        }
        // 方法为空实现，直接返回默认值
        if (method.returnType == void) {
            mv.visitInsn(Opcodes.RETURN)
        } else if (method.returnType.isPrimitive) {
            switch (method.returnType.name) {
                case "boolean": {
                    mv.visitInsn(Opcodes.ICONST_0);
                }
                case "byte": {
                    mv.visitInsn(Opcodes.ICONST_0);
                }
                case "char": {
                    mv.visitInsn(Opcodes.ICONST_0);
                }
                case "short": {
                    mv.visitInsn(Opcodes.ICONST_0);
                }
                case "int": {
                    mv.visitInsn(Opcodes.ICONST_0);
                }
                case "long": {
                    mv.visitInsn(Opcodes.LCONST_0);
                }
                case "float": {
                    mv.visitInsn(Opcodes.FCONST_0);
                }
                case "double": {
                    mv.visitInsn(Opcodes.DCONST_0);
                }
                default: {
                    mv.visitInsn(Opcodes.ACONST_NULL);
                }
            }
            mv.visitInsn(getReturnOpcode(method.returnType))
        } else {
            mv.visitInsn(Opcodes.ACONST_NULL)
            mv.visitInsn(Opcodes.ARETURN)
        }

        mv.visitMaxs(1, 1)
        mv.visitEnd()
    }

    /**
     * 获取对应类型的返回指令码
     */
    def getReturnOpcode(Class<?> type) {
        switch (type.name) {
            case "void": Opcodes.RETURN
            case "boolean": Opcodes.IRETURN
            case "byte": Opcodes.IRETURN
            case "char": Opcodes.IRETURN
            case "short": Opcodes.IRETURN
            case "int": Opcodes.IRETURN
            case "long": Opcodes.LRETURN
            case "float": Opcodes.FRETURN
            case "double": Opcodes.DRETURN
            default: Opcodes.ARETURN
        }
    }
}
